<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <title>服务器信息</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <script type="text/javascript" src="js/plugin/jquery.min.js"></script>
    <script type="text/javascript" src="js/plugin/vue/vue-2.4.2.min.js"></script>
    <style>
html,body{font-size:9px;margin:0;padding:0;height:100%;color:#999;overflow-x:hidden;}
.radius2{
    -webkit-border-radius: 2px;
    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    -moz-border-radius: 2px;
    border-radius: 2px;
    border-radius: 2px;
}
.percent{
    -webkit-border-radius: 5px;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    -moz-border-radius: 5px;
    border-radius: 5px;
    border-radius: 5px;
}
.memory{display:block;height:5px;background:#def;border:1px solid #777;width:250px;}
.percent{display:block;height:8px;background:#def;border:1px solid #777;width:250px;}
.percent2{display:block;height:4px;background:#def;border:1px solid #777;width:250px;}
.percent2 span, .percent span{display:block;height:100%;float:left;}
.memory span{display:block;height:100%;float:left;}
#statusPool{font-size:9px;}
.hide{display:none;}
.log_line{display: block;}
.log_time{color:#3AC}
.log_exception_title{color:#E33}
.red{color:#D33;}
.green{color:#3A3;}
.blue{color:#36D;}
.gray{color:#999;}
    </style>
</head>
<body>
<div id="body" :title="r">
    <!-- 应用信息 -->
    <span id="head_line">
        <span style="font-size:14px;color:#36F;">{{jvm.server_profile||""}}{{crawlerName||"节点"}} : </span>
        <span v-else> - </span>
        <span v-if="r && r < 60"><a href="?">自动刷新</a></span>
        <span v-else><a href="?r=8640000">停止刷新</a></span>
        <span>{{jvm.server_date}}</span>
    </span>
    <br/>
    <!-- jvm信息 -->
    <span id="server_line">
        <span>{{jvm.server_name}}:{{jvm.server_port}} @ {{jvm.server_pid}} - B: {{jvm.builderInfo}}</span>
    </span>
    <br/>
    <span id="memory_line">
      <span class="red">{{jvm.jvm_availableProcessors}}U </span>
      <span class="green">
        <span title="已用堆内存 heapMemoryUsage">{{parseInt(jvm.jvm_heapMemoryUsage?.used / 1048576)}} /</span>
        <span title="已申请堆内存 heapMemoryUsage">{{parseInt(jvm.jvm_heapMemoryUsage?.committed / 1048576)}} /</span>
        <span title="最大可用堆内存 heapMemoryUsage">{{parseInt(jvm.jvm_heapMemoryUsage?.max / 1048576)}}</span>
        <span> [</span>
        <span v-if="'Metaspace' in jvm.jvm_memory">
            <span title="已用非堆内存 Metaspace">{{parseInt(jvm.jvm_memory['Metaspace']?.used / 1048576)}} /</span>
            <span title="已申请非堆内存 Metaspace">{{parseInt(jvm.jvm_memory['Metaspace']?.committed / 1048576)}}</span>
            <span title="最大可用非堆内存 Metaspace">/ {{parseInt( (jvm.jvm_memory['Metaspace']?.max > 0 ? jvm.jvm_memory['Metaspace'].max : 0) / 1048576)}}</span>
        </span>
        <span v-if="'Perm Gen' in jvm.jvm_memory">
          <span title="已用非堆内存 Perm Gen">{{parseInt(jvm.jvm_memory['Perm Gen']?.used / 1048576)}} /</span>
          <span title="已申请非堆内存 Perm Gen">{{parseInt(jvm.jvm_memory['Perm Gen']?.committed / 1048576)}} /</span>
          <span title="最大可用非堆内存 Perm Gen">{{parseInt(jvm.jvm_memory['Perm Gen']?.max / 1048576)}}</span>
        </span>
        <span v-if="'Code Cache' in jvm.jvm_memory">
            <span title="代码缓冲区已用 Code Cache">- {{parseInt(jvm.jvm_memory['Code Cache']?.used / 1048576)}} /</span>
            <span title="代码缓冲区可用 Code Cache">{{parseInt(jvm.jvm_memory['Code Cache']?.max / 1048576)}}</span>
        </span>
        <span v-if="'Compressed Class Space' in jvm.jvm_memory">
            <span title="元数据已用 Compressed Class Space">- {{parseInt(jvm.jvm_memory['Compressed Class Space']?.used / 1048576)}} /</span>
            <span title="元数据可用 Compressed Class Space">{{parseInt(jvm.jvm_memory['Compressed Class Space']?.max / 1048576)}}</span>
        </span>
        <span>] </span>
      </span>
      <span class="blue">
        T: <span title="当前活跃线程数">{{jvm?.thread_count}}</span> / <span title="累计创建线程数">{{jvm?.thread_count_total_started}}</span>
      </span>

      <span class="radius2 memory">
        <span :style="radius1">
          <span :style="radius11">
            <span :style="radius111"><!--  --></span>
          </span>
        </span>
        <span :style="radius2">
          <span :style="radius21"><!--  --></span>
        </span>
      </span>
    </span>
    <!-- job -->
    <div class="job" v-for="(value, key) in jvm.task_Map">

        <span style="white-space:nowrap;">
              <a :href="['api/job_v2/jobStatus.json?statusKey=' + key]" :title="[value.heartTime + ': ' + value.jobName + ' ' +  value.target]" target="_blank">{{value.completionRate}}</a>
              <span>{{value.createTime}}:</span>
              <strong :title="[getDetailLog(value.detailLog)]">{{value.jobName}}</strong>
              <a :href="['api/job_v2/interrupt.json?statusKey=' + key]" title="结束任务" target="_blank">KILL</a>
              <br/>
              <a href="###" class="showAction showAction1" onclick="$('.showAction').removeClass('hide');$('.hideAction').addClass('hide');$('.showAction1').addClass('hide');$('.hideAction1').removeClass('hide');$('.info_div, .log_div').addClass('hide');$(this).closest('.job').find('.info_div').removeClass('hide')">展开明细</a>
              <a href="###" class="hideAction hideAction1 hide" onclick="$('.showAction').removeClass('hide');$('.hideAction').addClass('hide');$('.showAction1').removeClass('hide');$('.hideAction1').addClass('hide');$('.info_div, .log_div').addClass('hide');">隐藏明细</a>
              <a href="###" class="showAction showAction2" onclick="$('.showAction').removeClass('hide');$('.hideAction').addClass('hide');$('.showAction2').addClass('hide');$('.hideAction2').removeClass('hide');$('.info_div, .log_div').addClass('hide');$(this).closest('.job').find('.log_div').removeClass('hide')">展开日志</a>
              <a href="###" class="hideAction hideAction2 hide" onclick="$('.showAction').removeClass('hide');$('.hideAction').addClass('hide');$('.showAction2').removeClass('hide');$('.hideAction2').addClass('hide');$('.info_div, .log_div').addClass('hide');">隐藏日志</a>
              <span v-if="!value.exception" :title="[getDetailLog(value.detailLog)]">{{value.jobStatus}}</span>
              <span v-if="value.exception" :title="[omitLog(value.exception, 1024)]" style="color:F93">任务失败: {{omitLog(value.exception)}}</span>
        </span>

        <span class="percent2">
            <span :style="{width:value.completionRate,background:'#69F'}"><!--  --></span>
        </span>

        <div class="info_div hide">
            <div v-for="(value1, key1) in value">
                <strong>{{key1}}:</strong>
                <span v-if="value1 instanceof Array">
                    <span class="log_line" v-for="(line, idx) in value1" v-html="changeBr(line)"></span><br/>
                </span>
                <span v-else>{{value1}}</span>
            </div>
        </div>
        <div class="log_div hide">
            <span v-if="value.detailLog instanceof Array">
                <span class="log_line" v-for="(line, idx) in value.detailLog" v-html="changeBr(line)"></span><br/>
            </span>
            <span v-if="value.exception" class="log_exception"><span class="log_exception_title" style="color:F93">任务失败:</span> {{value.exception}}</span>
        </div>
    </div>
</div>

<script type="text/javascript">
    var init_ajax = 0;
    var timeInterval = getQueryString("r") || 5;
    var sybnInterval = null;
    var sybn = new Vue({
      el: '#body',
      data: {
        jvm:{
          server_date: "2018-05-23 18:30:13",
          server_name: "127.0.0.1",
          server_port: 80,
          server_pid: "",
          server_profile: "",
          jvm_runtime: "",
          builderInfo: "",
          jvm_availableProcessors: 4,
          jvm_freeMemory: 100,
          jvm_maxMemory: 100,
          jvm_totalMemory: 100,
          jvm_heapMemoryUsage: { init: 1, used: 1, committed: 1, max: 1 },
          jvm_nonHeapMemoryUsage: { init: 1, used: 1, committed: 1, max: 1 },
          jvm_maxMemory2: 1,
          jvm_memory: {
              'Eden Space': { committed: 1, max: 1, used: 1 },
              'Code Cache': { committed: 1, max: 1, used: 1 },
              'Survivor Space': { committed: 1, max: 1, used: 1 },
              'Compressed Class Space': { committed: 1, max: 1, used: 1 },
              'Metaspace': { committed: 1, max: 1, used: 1 },
              'Old Gen': { committed: 1, max: 1, used: 0 }
          },
          task_num: 0,
          task_Map: {},
          thread_count : 0,
          thread_count_total_started: 0,
          calBackStr: ""
        },
        r: getQueryString("r"),
        crawlerName: getQueryString("crawlerName"),
        crawlerName2: "服务器状态接口调用中..."
      },
      methods: {
        changeBr: function(content){
            // 换行符替换 时间高亮
            return content ? content.replace(/[\r\n]+/g,"</br>").replace(/^((\d\d)?\d\d-\d\d-\d\d( \d\d:\d\d:\d\d(\.\d\d\d)?)?)/,"<span class='log_time'>$1</span>") : content;
        },
        getCurrentTime: function() {
            //获取当前时间并打印
            var _this = this;
            let yy = new Date().getFullYear();
            let mm = new Date().getMonth()+1;
            let dd = new Date().getDate();
            let hh = new Date().getHours();
            let mf = new Date().getMinutes()<10 ? '0'+new Date().getMinutes() : new Date().getMinutes();
            let ss = new Date().getSeconds()<10 ? '0'+new Date().getSeconds() : new Date().getSeconds();
            _this.gettime = mm+'-'+dd+' '+hh+':'+mf+':'+ss;
            return _this.gettime;
        },
        refreshMessage: function() {
            if (init_ajax != 0 && window.frameElement != null){
                // 当前页面在 iframe 中, 且此 iframe 因为不在 active 中而被隐藏, 则跳过刷新
                var $tab_p = $(window.frameElement).closest('.tab-content>.tab-pane');
                if ($tab_p.length!=0 && !$tab_p.hasClass("active")) {
                    // TODO 待测试 return;
                }
            }
          $.ajax({
            url : "api/job_v2/status.json?jobType=" + getQueryString("jobType"),
            type : "get",
            dataType : "json",
            success : function(jvm) {
              sybn.jvm = jvm;
              init_ajax++;
            },
            error : function(jvm) {
              clearInterval(sybnInterval);
            }
          });
        }
      },
      computed: {
        radius1: function () {
          if ("jvm_heapMemoryUsage" in this.jvm) {
            return "width:" + (this.jvm.jvm_heapMemoryUsage.max / this.jvm.jvm_maxAllMemory * 100) + "%";
          } else {
            return "width:100%";
          }
        },
        radius11: function () {
          if ("jvm_heapMemoryUsage" in this.jvm) {
            return "width:" + (this.jvm.jvm_heapMemoryUsage.committed / this.jvm.jvm_heapMemoryUsage.max * 100) + "%;background:#6A9;";
          } else {
            return "width:0%";
          }
        },
        radius111: function () {
          if ("jvm_heapMemoryUsage" in this.jvm) {
            return "width:" + (this.jvm.jvm_heapMemoryUsage.used / this.jvm.jvm_heapMemoryUsage.committed * 100) + "%;background:#E56;";
          } else {
            return "width:0%";
          }
        },
        radius2: function () {
          if ("jvm_heapMemoryUsage" in this.jvm) {
              if (this.jvm.jvm_nonHeapMemoryUsage.max <= 0) {
                return "width:" + (this.jvm.jvm_nonHeapMemoryUsage.committed / this.jvm.jvm_maxAllMemory * 100) + "%;background:#6A9;";
              }
              return "width:" + (this.jvm.jvm_nonHeapMemoryUsage.max / this.jvm.jvm_maxAllMemory * 100) + "%;background:#6A9;";
          } else {
            return "width:0%";
          }
        },
        radius21: function () {
          if ("jvm_heapMemoryUsage" in this.jvm) {
            return "width:" + (this.jvm.jvm_nonHeapMemoryUsage.used / this.jvm.jvm_nonHeapMemoryUsage.committed * 100) + "%;background:#56E;";
          } else {
            return "width:0%";
          }
        },
      }
    });
    sybn.refreshMessage();
    sybnInterval = setInterval("sybn.refreshMessage()", timeInterval * 1000 );

    function getQueryString(name, defaults) {
      var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
      var r = window.location.search.substr(1).match(reg);
      if (r != null) return decodeURIComponent(r[2]); return defaults || null;
    }
    function getDetailLog(logList) {
      var res = logList.join('\r\n');
      if (res.length > 1024) {
        res = res.substr(0, 1021) + "...";
      }
      return res;
    }
    function omitLog(log, length) {
      var res = "" + log;
      length = length || 32;
      if (res.length > length && length > 3) {
        res = res.substr(0, length-3) + "...";
      }
      return res;
    }
  </script>
</body>
</html>
